using MediatR;
using WeatherSystem.API.Models;
using WeatherSystem.API.Repositories;
using WeatherSystem.API.Services;
using WeatherSystem.API.Specifications;

namespace WeatherSystem.API.CQRS.MediatR
{
    /// <summary>
    /// Weather data query handlers
    /// </summary>
    public class GetWeatherDataPagedHandler : IRequestHandler<GetWeatherDataPagedRequest, PagedResult<Dictionary<string, object>>>
    {
        private readonly IWeatherDataRepository _repository;
        private readonly ILogger<GetWeatherDataPagedHandler> _logger;

        public GetWeatherDataPagedHandler(IWeatherDataRepository repository, ILogger<GetWeatherDataPagedHandler> logger)
        {
            _repository = repository;
            _logger = logger;
        }

        public async Task<PagedResult<Dictionary<string, object>>> Handle(GetWeatherDataPagedRequest request, CancellationToken cancellationToken)
        {
            try
            {
                return await _repository.GetWeatherDataPagedAsync(
                    request.Page,
                    request.PageSize,
                    request.CityId,
                    request.StartDate,
                    request.EndDate,
                    request.Source,
                    request.SortBy,
                    request.SortDirection
                );
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取分页天气数据失败");
                throw;
            }
        }
    }

    public class GetLatestWeatherHandler : IRequestHandler<GetLatestWeatherRequest, WeatherDataEntry?>
    {
        private readonly IWeatherDataRepository _repository;
        private readonly ICacheService _cacheService;
        private readonly ILogger<GetLatestWeatherHandler> _logger;

        public GetLatestWeatherHandler(
            IWeatherDataRepository repository,
            ICacheService cacheService,
            ILogger<GetLatestWeatherHandler> logger)
        {
            _repository = repository;
            _cacheService = cacheService;
            _logger = logger;
        }

        public async Task<WeatherDataEntry?> Handle(GetLatestWeatherRequest request, CancellationToken cancellationToken)
        {
            try
            {
                var cacheKey = $"weather:latest:{request.CityId}";
                return await _cacheService.GetOrSetAsync(cacheKey, async () =>
                {
                    return await _repository.GetLatestByCityAsync(request.CityId);
                }, TimeSpan.FromMinutes(5));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取最新天气数据失败，城市ID: {CityId}", request.CityId);
                throw;
            }
        }
    }

    public class GetWeatherHistoryHandler : IRequestHandler<GetWeatherHistoryRequest, List<WeatherDataEntry>>
    {
        private readonly IWeatherDataRepository _repository;
        private readonly ICacheService _cacheService;
        private readonly ILogger<GetWeatherHistoryHandler> _logger;

        public GetWeatherHistoryHandler(
            IWeatherDataRepository repository,
            ICacheService cacheService,
            ILogger<GetWeatherHistoryHandler> logger)
        {
            _repository = repository;
            _cacheService = cacheService;
            _logger = logger;
        }

        public async Task<List<WeatherDataEntry>> Handle(GetWeatherHistoryRequest request, CancellationToken cancellationToken)
        {
            try
            {
                var cacheKey = $"weather:history:{request.CityId}:{request.StartDate:yyyyMMdd}:{request.EndDate:yyyyMMdd}";
                return await _cacheService.GetOrSetAsync(cacheKey, async () =>
                {
                    return await _repository.GetHistoryAsync(request.CityId, request.StartDate, request.EndDate);
                }, TimeSpan.FromMinutes(15));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取历史天气数据失败");
                throw;
            }
        }
    }

    /// <summary>
    /// Weather data command handlers
    /// </summary>
    public class CollectWeatherDataHandler : IRequestHandler<CollectWeatherDataRequest, WeatherDataEntry>
    {
        private readonly IWeatherService _weatherService;
        private readonly ILogger<CollectWeatherDataHandler> _logger;

        public CollectWeatherDataHandler(IWeatherService weatherService, ILogger<CollectWeatherDataHandler> logger)
        {
            _weatherService = weatherService;
            _logger = logger;
        }

        public async Task<WeatherDataEntry> Handle(CollectWeatherDataRequest request, CancellationToken cancellationToken)
        {
            try
            {
                return await _weatherService.CollectWeatherDataAsync(request.CityId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "采集天气数据失败，城市ID: {CityId}", request.CityId);
                throw;
            }
        }
    }

    public class CreateWeatherDataBatchHandler : IRequestHandler<CreateWeatherDataBatchRequest, List<Guid>>
    {
        private readonly IWeatherService _weatherService;
        private readonly ILogger<CreateWeatherDataBatchHandler> _logger;

        public CreateWeatherDataBatchHandler(IWeatherService weatherService, ILogger<CreateWeatherDataBatchHandler> logger)
        {
            _weatherService = weatherService;
            _logger = logger;
        }

        public async Task<List<Guid>> Handle(CreateWeatherDataBatchRequest request, CancellationToken cancellationToken)
        {
            try
            {
                return await _weatherService.CreateWeatherDataBatchAsync(request.Requests);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量创建天气数据失败");
                throw;
            }
        }
    }

    public class UpdateWeatherDataHandler : IRequestHandler<UpdateWeatherDataRequest, bool>
    {
        private readonly IWeatherService _weatherService;
        private readonly ILogger<UpdateWeatherDataHandler> _logger;

        public UpdateWeatherDataHandler(IWeatherService weatherService, ILogger<UpdateWeatherDataHandler> logger)
        {
            _weatherService = weatherService;
            _logger = logger;
        }

        public async Task<bool> Handle(UpdateWeatherDataRequest request, CancellationToken cancellationToken)
        {
            try
            {
                return await _weatherService.UpdateWeatherDataAsync(request.Id, request.UpdateRequest);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新天气数据失败，ID: {Id}", request.Id);
                throw;
            }
        }
    }

    public class DeleteWeatherDataHandler : IRequestHandler<DeleteWeatherDataRequest, bool>
    {
        private readonly IWeatherService _weatherService;
        private readonly ILogger<DeleteWeatherDataHandler> _logger;

        public DeleteWeatherDataHandler(IWeatherService weatherService, ILogger<DeleteWeatherDataHandler> logger)
        {
            _weatherService = weatherService;
            _logger = logger;
        }

        public async Task<bool> Handle(DeleteWeatherDataRequest request, CancellationToken cancellationToken)
        {
            try
            {
                return await _weatherService.DeleteWeatherDataAsync(request.Id);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除天气数据失败，ID: {Id}", request.Id);
                throw;
            }
        }
    }
}